from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404
from .models import Device, DeviceState, DeviceStateHistory, DeviceType
from apps.user.models import Family

class DeviceViewSet(viewsets.ModelViewSet):
    """
    提供 /devices/, /devices/{id}/,
         /devices/{id}/state (PATCH),
         /devices/{id}/state-history (GET) 等接口。
    """
    queryset = Device.objects.all().select_related('state')
    permission_classes = [IsAuthenticated]  # <-- 只允许已登录用户访问

    def create(self, request):
        name      = request.data.get('name')
        type_id   = request.data.get('type_id')
        family_id = request.data.get('family_id')
        meta      = request.data.get('meta', {})

        if not all([name, type_id, family_id]):
            return Response({'ok': False, 'error': 'Missing required fields'},
                            status=status.HTTP_400_BAD_REQUEST)

        device_type = get_object_or_404(DeviceType, id=type_id)
        family = get_object_or_404(Family, pk=family_id)

        # —— 可选：允许前端在创建时就传初始 state，否则用默认
        initial_state = request.data.get('state')
        if initial_state is None:
            # 生成一个“布尔 false，枚举第一个，数字最小值”的默认 state
            initial_state = {}
            for f, spec in device_type.capabilities.items():
                if spec is True:
                    initial_state[f] = False
                elif isinstance(spec, list):
                    initial_state[f] = spec[0]
                elif isinstance(spec, dict):
                    initial_state[f] = spec.get("min", 0)

        # 校验 initial_state
        ok, err = Device.validate_state(device_type.capabilities, initial_state)
        if not ok:
            return Response({'ok': False, 'error': err}, status=status.HTTP_400_BAD_REQUEST)

        # 创建设备
        device = Device.objects.create(
            name=name,
            type=device_type,
            family=family,
            meta=meta
        )
        # 创建状态快照
        DeviceState.objects.create(device=device, state_json=initial_state)

        return Response({
            'ok': True,
            'data': {
                'id': device.id,
                'name': device.name,
                'type': device.type.name,
                'family': device.family.name,
                'meta': device.meta,
                'state': initial_state
            }
        }, status=status.HTTP_201_CREATED)

    def list(self, request):
        devices = self.get_queryset()
        data = []
        for d in devices:
            data.append({
                'id': d.id,
                'name': d.name,
                'type': d.type.name,
                'family': d.family.name,
                'meta': d.meta,
                'state': d.state.state_json if hasattr(d, 'state') else {}
            })
        return Response({'ok': True, 'data': {'total': devices.count(), 'devices': data}})

    def retrieve(self, request, pk=None):
        d = get_object_or_404(self.queryset, pk=pk)
        result = {
            'id': d.id,
            'name': d.name,
            'type_id': d.type.name,
            'family': d.family.name,
            'meta': d.meta,
            'state': d.state.state_json if hasattr(d, 'state') else {}
        }
        if hasattr(d, 'state'):
            result['updated_at'] = d.state.updated_at.isoformat()
        return Response({'ok': True, 'data': result})

    def destroy(self, request, pk=None):
        d = get_object_or_404(Device, pk=pk)
        d.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(detail=True, methods=['patch'], url_path='state')
    def update_state(self, request, pk=None):
        """
        device:    Device 实例
        new_state: 新的状态 dict
        source:    DeviceStateHistory.Source.MANUAL or .SCENE
        """
        d = get_object_or_404(Device, pk=pk)
        new_state = request.data.get('state')
        if not isinstance(new_state, dict):
            return Response({'ok': False, 'error': 'State object required'},
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            # 直接调用模型方法，把 source 固定为 MANUAL
            d.apply_state(
                new_state,
                DeviceStateHistory.Source.MANUAL
            )
        except ValueError as e:
            # apply_state 里校验失败会抛 ValueError
            return Response(
                {'ok': False, 'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )

        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(detail=True, methods=['get'], url_path='state-history')
    def state_history(self, request, pk=None):
        qs = DeviceStateHistory.objects.filter(device_id=pk).order_by('ts')
        start = request.query_params.get('start_time')
        end   = request.query_params.get('end_time')
        if start:
            qs = qs.filter(ts__gte=start)
        if end:
            qs = qs.filter(ts__lte=end)

        data = [{'ts': h.ts.isoformat(), 'state': h.state_json} for h in qs]
        return Response({'ok': True, 'data': data})


class DeviceTypeViewSet(viewsets.ViewSet):
    """
    提供 /device-types/ (GET) 接口，
    返回每个 DeviceType 的 id、name，以及 capabilities 的字段列表。
    """
    permission_classes = [IsAuthenticated]  # <-- 同样需要登录
    def list(self, request):
        types = DeviceType.objects.all()
        data = [{
            'id':   dt.id,
            'name': dt.name,
            'capabilities': list(dt.capabilities.keys())
        } for dt in types]
        return Response({'ok': True, 'data': data}, status=status.HTTP_200_OK)